﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Quartz;
using Quartz.Impl;
using Quartz.Spi;
using System;
using System.Collections.Specialized;
using System.Threading;
using System.Threading.Tasks;

namespace H2O.Assistant.HostedServices
{
    public class QuartzHostedService : IHostedService, IDisposable
    {
        private readonly ILogger _logger;
        private readonly IConfiguration _configuration;
        private readonly IJobFactory _jobFactory;
        private IScheduler _scheduler;

        public QuartzHostedService(ILogger<QuartzHostedService> logger, IConfiguration configuration, IJobFactory jobFactory)
        {
            _logger = logger;
            _configuration = configuration;
            _jobFactory = jobFactory;
        }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation(message: "scheduler ready starting...");
                // quartz 的一些基础配置参数
                // 1. 可以用如下代码配置,
                // 2. 也是写到配置文件中后读取(这里采用这种方式, 以便后续维护).
                // quartz 官方提供的是 ini 配置文件(quartz.config), 这里可以改用 json, 以更符合 .NET Core 套路.
                //NameValueCollection props = new NameValueCollection();
                //props.Add(name: "quartz.serializer.type", value: "binary");
                NameValueCollection props = new NameValueCollection();
                //_configuration.GetSection(key: "quartz").GetChildren().Select(o => { true; });

                StdSchedulerFactory factory = new StdSchedulerFactory();

                // 获取一个调度器实例
                _scheduler = await factory.GetScheduler();
                _scheduler.JobFactory = _jobFactory;
                await _scheduler.Start();

                // 定义作业并将其绑定到我们的 HelloJob 类
                // 使用代码定义 Jobs & Triggers,
                // 也可以使用 quartz_jobs.xml 文件中定义.
                //IJobDetail job = JobBuilder.Create<NLogJob>()
                //    .WithIdentity("myJob", "group1")
                //    .Build();

                //// 触发这个作业并马上运行,之后每40秒执行一次
                //ITrigger trigger = TriggerBuilder.Create()
                //    .WithIdentity("myTrigger", "group1")
                //    .StartNow()
                //    .WithSimpleSchedule(x => x
                //        .WithIntervalInSeconds(3)
                //        .RepeatForever())
                //.Build();

                //await _scheduler.ScheduleJob(job, trigger);
                _logger.LogInformation(message: "scheduler is start.");
            }
            catch (SchedulerException ex)
            {
                _logger.LogError(message: $"scheduler start exception: {ex.ToString()}");
            }
        }

        public async Task StopAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation(message: "scheduler is shutdowning...");
            await _scheduler?.Shutdown(cancellationToken: cancellationToken);
            _logger.LogInformation(message: "scheduler is shutdown.");
        }

        public void Dispose()
        {
            _scheduler?.Shutdown();
        }
    }
}
